// editor
#include "DropDownScreen.h"
#include "ScreenGDIInfo.h"
#include "editorutil.h"

namespace editor {
DropDownScreen::DropDownScreen(int id, int customID, HWND hwnd, HDC parentDC, bool isUp,
        int x, int y,
        int width, int height,
        int minX, int minY,
        int offX, int offY
        ) :
    AbstractScreen(id, x, y, width, height, minX, minY, offX, offY),
    customID_(customID),
    hWnd_(hwnd),
    parentDC_(parentDC),
    list_(),
    selectedIdx_(0),
    viewSize_(5),
    viewStartIdx_(0),
    leftOffset_(2),
    rightOffset_(2),
    itemOffset_(1),
    isUpdirection_(isUp),
    cinfo_(g_cinfo),
    finfo_(g_finfo)
{
    fitListDisp();
}

DropDownScreen::~DropDownScreen() {
}

bool DropDownScreen::sendKey(short key, bool repeat) {
    return false;
}

void DropDownScreen::update() {
    updateState_.request(DD_SCR_ALL);
    tryUpdate();
}

void DropDownScreen::draw() {
}

size_t DropDownScreen::itemSize() const {
    return list_.size();
}

size_t DropDownScreen::viewSize() const {
    return viewSize_;
}

size_t DropDownScreen::viewStartIdx() const {
    return viewStartIdx_;
}

void DropDownScreen::addItem(const std::pair<std::string, boost::any>& item) {
    list_.push_back(item);
}

void DropDownScreen::insertItem(size_t idx, const std::pair<std::string, boost::any>& item) {
    list_.insert(list_.begin()+idx, item);
}

void DropDownScreen::removeItem(size_t idx) {
    list_.erase(list_.begin() + idx);
    if (selectedIdx_ >= list_.size()) selectedIdx_ = list_.size()-1;
}

void DropDownScreen::clearItems() {
    list_.clear();
    selectedIdx_ = 0;
}

std::string DropDownScreen::getName(size_t idx) const {
    return list_[idx].first;
}

boost::any DropDownScreen::getValue(size_t idx) const {
    return list_[idx].second;
}

void DropDownScreen::setValue(size_t idx, boost::any v) {
    list_[idx].second = v;
}

void DropDownScreen::selectItem(size_t idx) {
    if (selectedIdx_ == idx) return;
    selectedIdx_ = idx;
    if (selectedIdx_ < viewStartIdx_) {
        viewStartIdx_ = selectedIdx_;
    } else if (selectedIdx_ >= viewStartIdx_ + viewSize_) {
        viewStartIdx_ = selectedIdx_ - viewSize_ + 1;
    }
    update();
}

size_t DropDownScreen::selectedIdx() const {
    return selectedIdx_;
}

bool DropDownScreen::tryUpdate() {
    if (!updateState_.isRequested(DD_SCR_BACKGROUD)) return false;

    ScopedBrush brush(cinfo_.colorRef(DD_COLOR_BG));
    parentDC_.select(brush);
    PatBlt(parentDC_.get(), x_, y_, width_, height_, PATCOPY);

    ScopedBrush selectedBrush(cinfo_.colorRef(DD_COLOR_SELECTED_BG));
    parentDC_.select(selectedBrush);
    int oldmode = SetBkMode(parentDC_.get(), TRANSPARENT);
    const FontInfo& finfo = finfo_.fontInfo(DD_FONT_NORMAL);
    ScopedFont font(finfo);
    parentDC_.select(font);
    SIZE sz;
    if (GetTextExtentPoint32(parentDC_.get(), " ", 1, &sz)) return false;
    int itemHeight = sz.cx + 2*itemOffset_;
    SetTextColor(parentDC_.get(), finfo.color());
    size_t viewSz = max(viewSize_, list_.size());
    if (isUpdirection_) {
        size_t selectedIdxFromTop = viewSz - (selectedIdx_ - viewStartIdx_);
        PatBlt(parentDC_.get(), x_, y_+selectedIdxFromTop*itemHeight, width_, itemHeight, PATCOPY);
        for (size_t i = 0; i < viewSz; ++i) {
            parentDC_.textout(x_+leftOffset_, y_+i*itemHeight+itemOffset_, getName(viewStartIdx_+(viewSz-i)));
        }
    } else {
        size_t selectedIdxFromTop = selectedIdx_ - viewStartIdx_;
        PatBlt(parentDC_.get(), x_, y_+selectedIdxFromTop*itemHeight, width_, itemHeight, PATCOPY);
        for (size_t i = 0; i < viewSz; ++i) {
            parentDC_.textout(x_+leftOffset_, y_+i*itemHeight+itemOffset_, getName(viewStartIdx_+i));
        }
    }

    if (oldmode) {
        SetBkMode(parentDC_.get(), oldmode);
    }

    updateState_.end(DD_SCR_ALL);
    return true;
}

void DropDownScreen::fitListDisp() {
    FontInfo fi = finfo_.fontInfo(DD_FONT_NORMAL);
    ScopedFont font(fi);
    parentDC_.select(font);
    SIZE sz;
    if (GetTextExtentPoint32(parentDC_.get(), " ", 1, &sz)) {
        int height = sz.cx;
        updateSize(x_, y_, width_, (height+2*itemOffset_)*max(viewSize_, list_.size()));
    }
}


} // end of namespace editor
